/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package astroim.samp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.astrogrid.samp.Client;
import org.astrogrid.samp.Message;
import org.astrogrid.samp.Metadata;
import org.astrogrid.samp.client.AbstractMessageHandler;
import org.astrogrid.samp.client.ClientProfile;
import org.astrogrid.samp.client.DefaultClientProfile;
import org.astrogrid.samp.client.HubConnection;
import org.astrogrid.samp.client.HubConnector;
import org.astrogrid.samp.client.SampException;

/**
 *
 * @author alykhalid
 */
public class LocalConnector {
    public static final String NAME = "AstroIM";
    public static final String DESCRIPTION = "Astro Grid Interactive Instant Messenger";
    public HubConnector connection = null;
    public String ID;
    private boolean processRegisteration = false;
    private Map RegisteredClientsID = new HashMap<String, String>();
    private ArrayList<ProxyClient> RegisteredProxyClients = new ArrayList<ProxyClient>();
    public HashMap<Map, Map> ClientMapProperties = null;

    public LocalConnector registerWithHUb() throws SampException {
        ClientProfile profile = DefaultClientProfile.getProfile();
        connection = new HubConnector(profile);

        Metadata meta = new Metadata();
        meta.setName(NAME);
        meta.setDescriptionText(DESCRIPTION);
        connection.declareMetadata(meta);
        ID = connection.getConnection().getRegInfo().getSelfId();
        connection.addMessageHandler(new AbstractMessageHandler("samp.hub.event.register") {

            @Override
            public Map processCall(HubConnection Hubconnection, String senderId, Message message) throws Exception {
                if (processRegisteration) {
                    Object ID = message.getParam("id");
                    String strID = (String) ID;
                    Thread.sleep(200);
                    Metadata metadata = Hubconnection.getMetadata(strID);
                    if (!RegisteredClientsID.containsValue(strID)) {
                        ProxyClient pc = new ProxyClient();
                        processRegisteration = false;
                        RegisteredClientsID.put(strID, pc.setClientName("Proxy").setDescription(metadata.getDescriptionText()).setName(metadata.getName()).setRegisteredSubscriptions(Hubconnection.getSubscriptions(strID)).registerWithHub().LocalID);
                        RegisteredProxyClients.add(pc);
                        processRegisteration = true;
                    }
                }
                return message;
            }
        });

        connection.addMessageHandler(new AbstractMessageHandler("samp.hub.event.unregister") {

            @Override
            public Map processCall(HubConnection Hubconnection, String senderId, Message message) throws Exception {
                Object ID = message.getParam("id");
                String strID = (String) ID;
                System.out.println("Check: " + strID);
                if (RegisteredClientsID.containsKey(strID)) {
                    int index = 0;
                    for (ProxyClient pc : RegisteredProxyClients) {
                        if (RegisteredClientsID.get(strID).equals(pc.LocalID)) {
                            pc.unregisterFromHub();
                            break;
                        }
                        index++;
                    }
                    RegisteredProxyClients.remove(index);
                    RegisteredClientsID.remove(strID);
                }
                return message;
            }
        });

        connection.declareSubscriptions(connection.computeSubscriptions());
        //connection.getConnection().notifyAll(new Message("samp.app.ping"));
        return this;
    }

    public LocalConnector getRegisteredClients() {
        ClientMapProperties = new HashMap<Map, Map>();
        Map TempMap = Collections.synchronizedMap(connection.getClientMap());
        Set s = TempMap.entrySet();
        synchronized (TempMap) {
            Iterator i = s.iterator();
            while (i.hasNext()) {
                Map.Entry pairs = (Map.Entry) i.next();
                System.out.println(pairs.getKey() + "=" + pairs.getValue());
                Client c = (Client) pairs.getValue();
                Map TempClientIDMap = new HashMap<String, String>();
                TempClientIDMap.put(pairs.getKey().toString(), pairs.getValue().toString());
                ClientMapProperties.put(TempClientIDMap, c.getSubscriptions());
            }
        }
        return this;
    }

    public LocalConnector registerProxyClients() throws SampException {
        Iterator itClientMap = ClientMapProperties.entrySet().iterator();
        while (itClientMap.hasNext()) {
            Map.Entry<Map, Map> ClientMapPairs = (Map.Entry<Map, Map>) itClientMap.next();
            Iterator itClientIDMap = ClientMapPairs.getKey().entrySet().iterator();
            while (itClientIDMap.hasNext()) {
                Map.Entry<String, String> ClientIDMapPairs = (Map.Entry<String, String>) itClientIDMap.next();
                if ((!NAME.equals(ClientIDMapPairs.getValue())) && (!"Hub".equals(ClientIDMapPairs.getValue()))) {
                    ProxyClient pc = new ProxyClient();
                    processRegisteration = false;
                    RegisteredClientsID.put(ClientIDMapPairs.getKey(), pc.setClientName("Proxy").setDescription("").setName(ClientIDMapPairs.getValue()).setRegisteredSubscriptions(ClientMapPairs.getValue()).registerWithHub().LocalID);
                    RegisteredProxyClients.add(pc);
                    processRegisteration = true;
                }
            }
        }
        processRegisteration = true;
        return this;
    }

    public static LocalConnector getInstance() {
        return LocalConnectorHolder.INSTANCE;
    }

    private static class LocalConnectorHolder {

        private static final LocalConnector INSTANCE = new LocalConnector();
    }
}
